/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.openide.nodes; import java.awt.Image; import java.awt.datatransfer.Transferable; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.beans.PropertyEditor; import java.beans.FeatureDescriptor; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.util.Enumeration; import java.util.*; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import org.openide.util.datatransfer.NewType; import org.openide.util.datatransfer.PasteType; import org.openide.util.HelpCtx; import org.openide.util.Mutex; import org.openide.util.actions.SystemAction; /** A proxy for another node. * Unless otherwise mentioned, all methods of the original node are delegated to. * If desired, you can disable delegation of certain methods which are concrete in <code>Node</code> * by calling {@link #disableDelegation}. * * @author Jaroslav Tulach */ public class FilterNode extends Node { /** node to delegate to */ private Node original; /** listener to property changes, * accessible thru getPropertyChangeListener */ private PropertyChangeListener propL; /** listener to node changes * Accessible thru get node listener */ private NodeListener nodeL; // Note: int (not long) to avoid need to ever synchronize when accessing it // (Java VM spec does not guarantee that long's will be stored atomically) /** @see #delegating */ private int delegateMask; /** Whether to delegate <code>setName</code>. */ protected static final int DELEGATE_SET_NAME = 1 << 0; /** Whether to delegate <code>getName</code>. */ protected static final int DELEGATE_GET_NAME = 1 << 1; /** Whether to delegate <code>setDisplayName</code>. */ protected static final int DELEGATE_SET_DISPLAY_NAME = 1 << 2; /** Whether to delegate <code>getDisplayName</code>. */ protected static final int DELEGATE_GET_DISPLAY_NAME = 1 << 3; /** Whether to delegate <code>setShortDescription</code>. */ protected static final int DELEGATE_SET_SHORT_DESCRIPTION = 1 << 4; /** Whether to delegate <code>getShortDescription</code>. */ protected static final int DELEGATE_GET_SHORT_DESCRIPTION = 1 << 5; /** Whether to delegate <code>destroy</code>. */ protected static final int DELEGATE_DESTROY = 1 << 6; /** Whether to delegate <code>getActions</code>. */ protected static final int DELEGATE_GET_ACTIONS = 1 << 7; /** Whether to delegate <code>getContextActions</code>. */ protected static final int DELEGATE_GET_CONTEXT_ACTIONS = 1 << 8; /** Mask indicating delegation of all possible methods. */ private static final int DELEGATE_ALL = DELEGATE_SET_NAME | DELEGATE_GET_NAME | DELEGATE_SET_DISPLAY_NAME | DELEGATE_GET_DISPLAY_NAME | DELEGATE_SET_SHORT_DESCRIPTION | DELEGATE_GET_SHORT_DESCRIPTION | DELEGATE_DESTROY | DELEGATE_GET_ACTIONS | DELEGATE_GET_CONTEXT_ACTIONS; /** Create proxy. * @param original the node to delegate to */ public FilterNode(Node original) { this ( original, original.isLeaf () ? org.openide.nodes.Children.LEAF : new Children (original) ); } /** Create proxy with a different set of children. * * @param original the node to delegate to * @param children a set of children for this node */ public FilterNode( Node original, org.openide.nodes.Children children ) { super (children); this.original = original; init (); } /** Initializes the node. */ private void init () { original.addPropertyChangeListener (getPropertyChangeListener ()); original.addNodeListener (getNodeListener ()); delegateMask = DELEGATE_ALL; } /** Removes all listeners (property and node) on * the original node. Called from {@link NodeListener#nodeDestroyed}, * but can be called by any subclass to stop reflecting changes * in the original node. */ protected void finalize () { original.removePropertyChangeListener (getPropertyChangeListener ()); original.removeNodeListener (getNodeListener ()); } /** Enable delegation of a set of methods. * These will be delegated to the original node. * Since all available methods are delegated by default, normally you will not need to call this. * @param mask bitwise disjunction of <code>DELEGATE_XXX</code> constants * @throws IllegalArgumentException if the mask is invalid */ protected final void enableDelegation (int mask) { if ((mask & ~DELEGATE_ALL) != 0) throw new IllegalArgumentException ("Bad delegation mask: " + mask); // NOI18N delegateMask |= mask; } /** Disable delegation of a set of methods. * The methods will retain their behavior from {@link Node}. * <p>For example, if you wish to subclass <code>FilterNode</code>, giving your * node a distinctive display name and tooltip, and performing some special * action upon deletion, you may do so without risk of affecting the original * node as follows: * <br><code><pre> * public MyNode extends FilterNode { * public MyNode (Node orig) { * super (orig, new MyChildren (orig)); * disableDelegation (DELEGATE_GET_DISPLAY_NAME | DELEGATE_SET_DISPLAY_NAME | * DELEGATE_GET_SHORT_DESCRIPTION | DELEGATE_SET_SHORT_DESCRIPTION | * DELEGATE_DESTROY); * // these will affect only the filter node: * setDisplayName ("Linking -> " + orig.getDisplayName ()); * setShortDescription ("Something different."); * } * public boolean canRename () { return false; } * public void destroy () throws IOException { * doMyCleanup (); * super.destroy (); // calls Node.destroy(), not orig.destroy() * } * } * </pre></code> * <br>You may still manually delegate where desired using {@link #getOriginal}. * Other methods abstract in <code>Node</code> may simply be overridden without * any special handling. * @param mask bitwise disjunction of <code>DELEGATE_XXX</code> constants * @throws IllegalArgumentException if the mask is invalid */ protected final void disableDelegation (int mask) { if ((mask & ~DELEGATE_ALL) != 0) throw new IllegalArgumentException ("Bad delegation mask: " + mask); // NOI18N delegateMask &= ~mask; } /** Test whether we are currently delegating to some method. */ private final boolean delegating (int what) { return (delegateMask & what) != 0; } /** Create new filter node for the original. * Subclasses do not have to override this, but if they do not, * the default implementation will filter the subclass filter, which is not * very efficient. * @return copy of this node */ public Node cloneNode () { if (isDefault ()) { // this is realy filter node without changed behaviour // with the normal children => use normal constructor for the // original node return new FilterNode (original); } else { // create filter node for this node to reflect changed // behaviour return new FilterNode (this); } } // ------------- START OF DELEGATED METHODS ------------ /* Setter for system name. Fires info about property change. * @param s the string */ public void setName (String s) { if (delegating (DELEGATE_SET_NAME)) original.setName (s); else super.setName (s); } /* @return the name of the original node */ public String getName () { if (delegating (DELEGATE_GET_NAME)) return original.getName (); else return super.getName (); } /* Setter for display name. Fires info about property change. * @param s the string */ public void setDisplayName (String s) { if (delegating (DELEGATE_SET_DISPLAY_NAME)) original.setDisplayName (s); else super.setDisplayName (s); } /* @return the display name of the original node */ public String getDisplayName () { if (delegating (DELEGATE_GET_DISPLAY_NAME)) return original.getDisplayName (); else return super.getDisplayName (); } /* Setter for short description. Fires info about property change. * @param s the string */ public void setShortDescription (String s) { if (delegating (DELEGATE_SET_SHORT_DESCRIPTION)) original.setShortDescription (s); else super.setShortDescription (s); } /* @return the description of the original node */ public String getShortDescription () { if (delegating (DELEGATE_GET_SHORT_DESCRIPTION)) return original.getShortDescription (); else return super.getShortDescription (); } /* Finds an icon for this node. Delegates to the original. * * @see java.bean.BeanInfo * @param type constants from <CODE>java.bean.BeanInfo</CODE> * @return icon to use to represent the bean */ public Image getIcon (int type) { return original.getIcon (type); } /* Finds an icon for this node. This icon should represent the node * when it is opened (if it can have children). Delegates to original. * * @see java.bean.BeanInfo * @param type constants from <CODE>java.bean.BeanInfo</CODE> * @return icon to use to represent the bean when opened */ public Image getOpenedIcon (int type) { return original.getOpenedIcon (type); } public HelpCtx getHelpCtx () { return original.getHelpCtx (); } /* Can the original node be renamed? * * @return true if the node can be renamed */ public boolean canRename () { return original.canRename (); } /* Can the original node be deleted? * @return <CODE>true</CODE> if can, <CODE>false</CODE> otherwise */ public boolean canDestroy () { return original.canDestroy (); } /* Degelates the delete operation to original. */ public void destroy () throws java.io.IOException { if (delegating (DELEGATE_DESTROY)) original.destroy (); else super.destroy (); } /** Used to access the destroy method when original nodes * has been deleted */ private final void originalDestroyed () { try { super.destroy (); } catch (IOException ex) { } } /* Getter for the list of property sets. Delegates to original. * * @return the array of property sets. */ public PropertySet[] getPropertySets () { return original.getPropertySets (); } /* Called when an object is to be copied to clipboard. * @return the transferable object dedicated to represent the * content of clipboard * @exception IOException is thrown when the * operation cannot be performed */ public Transferable clipboardCopy () throws IOException { return original.clipboardCopy (); } /* Called when an object is to be cut to clipboard. * @return the transferable object dedicated to represent the * content of clipboard * @exception IOException is thrown when the * operation cannot be performed */ public Transferable clipboardCut () throws IOException { return original.clipboardCut (); } /* Returns true if this object allows copying. * @returns true if this object allows copying. */ public boolean canCopy () { return original.canCopy (); } /* Returns true if this object allows cutting. * @returns true if this object allows cutting. */ public boolean canCut () { return original.canCut (); } public Transferable drag () throws IOException { return original.drag (); } /* Default implementation that tries to delegate the implementation * to the createPasteTypes method. Simply calls the method and * tries to take the first provided argument. Ignores the action * argument and index. * * @param t the transferable * @param action the drag'n'drop action to do DnDConstants.ACTION_MOVE, ACTION_COPY, ACTION_LINK * @param index index between children the drop occured at or -1 if not specified * @return null if the transferable cannot be accepted or the paste type * to execute when the drop occures */ public PasteType getDropType (Transferable t, int action, int index) { return original.getDropType (t, action, index); } /* Which paste operations are allowed when transferable t is in clipboard? * @param t the transferable in clipboard * @return array of operations that are allowed */ public PasteType[] getPasteTypes (Transferable t) { return original.getPasteTypes (t); } /* Support for new types that can be created in this node. * @return array of new type operations that are allowed */ public NewType[] getNewTypes () { return original.getNewTypes (); } /* Delegates to original. * * @return array of system actions that should be in popup menu */ public SystemAction[] getActions () { if (delegating (DELEGATE_GET_ACTIONS)) return original.getActions (); else return super.getActions (); } /* Delegates to original */ public SystemAction[] getContextActions () { if (delegating (DELEGATE_GET_CONTEXT_ACTIONS)) return original.getContextActions (); else return super.getContextActions (); } /* * @return default action of the original node or null */ public SystemAction getDefaultAction () { return original.getDefaultAction (); } /* * @return <CODE>true</CODE> if the original has a customizer. */ public boolean hasCustomizer () { return original.hasCustomizer (); } /* Returns the customizer component. * @return the component or <CODE>null</CODE> if there is no customizer */ public java.awt.Component getCustomizer () { return original.getCustomizer (); } /* Delegates to original. * * @param type the class to look for * @return instance of that class or null if this class of cookie * is not supported */ public Node.Cookie getCookie (Class type) { return original.getCookie (type); } /** If this is FilterNode without any changes (subclassed, changed children) * and the original provides handle, stores them and * returns a new handle for the proxy. * <p>Subclasses <strong>must</strong> override this if they wish for their nodes to be * properly serializable. * * @return the handle, or <code>null</code> if this node is subclassed or * uses changed children */ public Node.Handle getHandle () { if (!isDefault ()) { // subclasses has to implement the method by its own return null; } Node.Handle original = this.original.getHandle (); if (original == null) { // no original handle => no handle here return null; } return new FilterHandle (original); } /** Test equality of original nodes. * Note that for subclasses of <code>FilterNode</code>, or filter nodes with non-default children, * the test reverts to object identity. * @param o something to compare to, presumably a node or <code>FilterNode</code> of one * @return true if this node's original node is the same as the parameter (or original node of parameter) */ public boolean equals (Object o) { // VERY DANGEROUS! Completely messes up visualizers and often original node is displayed rather than filter. // Jst: I know that it is dangerous, but some code probably depends on it // if (!isDefault ()) { return super.equals (o); } if (o instanceof FilterNode) { FilterNode fn = (FilterNode)o; return fn.isDefault () && original.equals (fn.original); } // o isn't filter node, compare with original return original.equals(o); } /** Hash by original nodes. * Note that for subclasses of <code>FilterNode</code>, or filter nodes with non-default children, * the hash reverts to the identity hash code. * @return the delegated hash code */ public int hashCode () { // JST: Pretty, pretty please with suggar on the top, do not comment this // method out or I spend next two hours looking for why filternodes are // not removed from hashtable even they are equal! return isDefault () ? original.hashCode () : super.hashCode (); } // public String toString () { // return super.toString () + " original has children: " + original.getChildren ().getNodesCount (); // NOI18N // } // ----------- END OF DELEGATED METHODS ------------ /** Get the original node. * @return the node proxied to */ protected Node getOriginal () { return original; } /** Create a property change listener that allows listening on the * original node properties (contained in property sets) and propagating * them to the proxy. * <P> * This method is called during initialization and allows subclasses * to modify the default behaviour. * * @return a {@link PropertyChangeAdapter} in the default implementation */ protected PropertyChangeListener createPropertyChangeListener () { return new PropertyChangeAdapter (this); } /** Creates a node listener that allows listening on the * original node and propagating events to the proxy. * <p>Intended for overriding by subclasses, as with {@link #createPropertyChangeListener}. * * @return a {@link NodeAdapter} in the default implementation */ protected NodeListener createNodeListener () { return new NodeAdapter (this); } /** Getter for property change listener. */ synchronized PropertyChangeListener getPropertyChangeListener () { if (propL == null) { propL = createPropertyChangeListener (); } return propL; } /** Getter for node listener. */ synchronized NodeListener getNodeListener () { if (nodeL == null) { nodeL = createNodeListener (); } return nodeL; } /** Check method whether the node has default behaviour or * if it is either subclass of uses different children. * @return true if it is default */ private boolean isDefault () { if (getClass () != FilterNode.class) { return false; } org.openide.nodes.Children ch = getChildren (); if ((original.isLeaf () && ch == Children.LEAF) || (! original.isLeaf () && ch.getClass () == /* FilterNode. */ Children.class && ((Children) ch).original == original)) { return true; } else { return false; } } /** Adapter that listens on changes in an original node * and refires them in a proxy. * This adapter is created during * initialization in {@link FilterNode#createPropertyChangeListener}. The method * can be overriden and this class used as the super class for the * new implementation. * <P> * A reference to the proxy is stored by weak reference, so it does not * prevent the node from being finalized. */ protected static class PropertyChangeAdapter extends Object implements PropertyChangeListener { /** weak reference to filter node */ private WeakReference fn; /** Create a new adapter. * @param fn the proxy */ public PropertyChangeAdapter (FilterNode fn) { this.fn = new WeakReference (fn); } /* Find the node we are attached to. If it is not null call property * change method with two arguments. */ public final void propertyChange (PropertyChangeEvent ev) { FilterNode fn = (FilterNode)this.fn.get (); if (fn == null) { return; } propertyChange (fn, ev); } /** Actually propagate the event. * Intended for overriding. * @param fn the proxy * @param ev the event */ protected void propertyChange (FilterNode fn, PropertyChangeEvent ev) { fn.firePropertyChange ( ev.getPropertyName (), ev.getOldValue (), ev.getNewValue () ); } } /** Adapter that listens on changes in an original node and refires them * in a proxy. Created in {@link FilterNode#createNodeListener}. * @see FilterNode.PropertyChangeAdapter */ protected static class NodeAdapter extends Object implements NodeListener { /** weak reference to filter node */ private WeakReference fn; /** children object to notify about addition of children. * Can be null. Set from Children's initNodes method. */ private WeakReference children; /** Create an adapter. * @param fn the proxy */ public NodeAdapter (FilterNode fn) { this.fn = new WeakReference (fn); } /* Tests if the reference to the node provided in costructor is * still valid (it has not been finalized) and if so, calls propertyChange (Node, ev). */ public final void propertyChange (PropertyChangeEvent ev) { FilterNode fn = (FilterNode)this.fn.get (); if (fn == null) { return; } propertyChange (fn, ev); } /** Actually refire the change event in a subclass. * The default implementation ignores changes of the <code>parentNode</code> property but refires * everything else. * * @param fn the filter node * @param ev the event to fire */ protected void propertyChange (FilterNode fn, PropertyChangeEvent ev) { String n = ev.getPropertyName (); if (n.equals (Node.PROP_PARENT_NODE)) { // does nothing return; } if (n.equals (Node.PROP_DISPLAY_NAME)) { fn.fireOwnPropertyChange ( PROP_DISPLAY_NAME, (String)ev.getOldValue (), (String)ev.getNewValue () ); return; } if (n.equals (Node.PROP_NAME)) { fn.fireOwnPropertyChange ( PROP_NAME, (String)ev.getOldValue (), (String)ev.getNewValue () ); return; } if (n.equals (Node.PROP_SHORT_DESCRIPTION)) { fn.fireOwnPropertyChange ( PROP_SHORT_DESCRIPTION, (String)ev.getOldValue (), (String)ev.getNewValue () ); return; } if (n.equals (Node.PROP_ICON)) { fn.fireIconChange (); return; } if (n.equals (Node.PROP_OPENED_ICON)) { fn.fireOpenedIconChange (); return; } if (n.equals (Node.PROP_PROPERTY_SETS)) { fn.firePropertySetsChange ((PropertySet[])ev.getOldValue (), (PropertySet[])ev.getNewValue ()); return; } if (n.equals (Node.PROP_COOKIE)) { fn.fireCookieChange (); return; } } /** Does nothing. * @param ev event describing the action */ public void childrenAdded (NodeMemberEvent ev) { } /** Does nothing. * @param ev event describing the action */ public void childrenRemoved (NodeMemberEvent ev) { } /** Does nothing. * @param ev event describing the action */ public void childrenReordered (NodeReorderEvent ev) { } /* Does nothing. * @param ev event describing the node */ public final void nodeDestroyed (NodeEvent ev) { FilterNode fn = (FilterNode)this.fn.get (); if (fn == null) { return; } fn.originalDestroyed (); } } /** Children for a filter node. Listens on changes in subnodes of * the original node and asks this filter node to creates representants for * these subnodes. * <P> * This class is used as the default for subnodes of filter node, but * subclasses may modify it or provide a totally different implementation. */ public static class Children extends org.openide.nodes.Children.Keys implements Cloneable { /** Original node. Should not be modified. */ protected Node original; /** node listener on original */ private NodeListener nodeL; /** Create children. * @param or original node to take children from */ public Children (Node or) { original = or; } /** Closes the listener, if any, on the original node. */ protected void finalize () { if (nodeL != null) original.removeNodeListener (nodeL); nodeL = null; } /* Clones the children object. */ public Object clone () { return new Children (original); } /** Initializes listening to changes in original node. */ protected void addNotify () { // add itself to reflect to changes children of original node nodeL = new ChildrenAdapter (this); original.addNodeListener (nodeL); updateKeys (); } /** Clears current keys, because all mirrored nodes disappeared. */ protected void removeNotify () { setKeys (Collections.EMPTY_SET); if (nodeL != null) { original.removeNodeListener (nodeL); nodeL = null; } } /** Allows subclasses to override * creation of node representants for nodes in the mirrored children * list. The default implementation simply uses {@link Node#cloneNode}. * <p>Note that this method is only suitable for a 1-to-1 mirroring. * * @param node node to create copy of * @return copy of the original node */ protected Node copyNode (Node node) { return node.cloneNode (); } /* Implements find of child by finding the original child and then [PENDING] * @param name of node to find * @return the node or null */ public Node findChild (String name) { original.getChildren ().findChild (name); return super.findChild (name); } /** Create nodes representing copies of the original node's children. * The default implementation returns exactly one representative for each original node, * as returned by {@link #copyNode}. * Subclasses may override this to avoid displaying a copy of an original child at all, * or even to display multiple nodes representing the original. * @param key the original child node * @return zero or more nodes representing the original child node */ protected Node[] createNodes (Object key) { Node n = (Node)key; // is run under read access lock so nobody can change children return new Node[] { copyNode (n) }; } /* Delegates to children of the original node. * * @param arr nodes to add * @return true/false */ public boolean add (Node[] arr) { return original.getChildren ().add (arr); } /* Delegates to filter node. * @param arr nodes to remove * @return true/false */ public boolean remove (Node[] arr) { return original.getChildren ().remove (arr); } /** Called when the filter node adds a new child. * The default implementation makes a corresponding change. * @param ev info about the change */ protected void filterChildrenAdded (NodeMemberEvent ev) { updateKeys (); } /** Called when the filter node removes a child. * The default implementation makes a corresponding change. * @param ev info about the change */ protected void filterChildrenRemoved (NodeMemberEvent ev) { updateKeys (); } /** Called when the filter node reorders its children. * The default implementation makes a corresponding change. * @param ev info about the change */ protected void filterChildrenReordered (NodeReorderEvent ev) { updateKeys (); } /** variable to notify that there is a cyclic update. * Used only in updateKeys method */ // private transient boolean cyclic; /** Update keys from original nodes */ private void updateKeys () { // if (!cyclic) { // cyclic = true; Children.MUTEX.postWriteRequest (new Runnable () { public void run () { Node[] arr = original.getChildren ().getNodes (); setKeys (arr); } }); // cyclic = false; // } } } /** Adapter that listens on changes in the original node and fires them * in this node. * Used as the default listener in {@link FilterNode.Children}, * and is intended for refinement by its subclasses. */ private static class ChildrenAdapter extends Object implements NodeListener { /** children object to notify about addition of children. * Can be null. Set from Children's initNodes method. */ private WeakReference children; /** Create a new adapter. * @param ch the children list */ public ChildrenAdapter (Children ch) { this.children = new WeakReference (ch); } /** Does nothing. * @param ev the event */ public void propertyChange (PropertyChangeEvent ev) { } /* Informs that a set of new children has been added. * @param ev event describing the action */ public void childrenAdded (NodeMemberEvent ev) { Children children = (Children)this.children.get (); if (children == null) return; children.filterChildrenAdded (ev); } /* Informs that a set of children has been removed. * @param ev event describing the action */ public void childrenRemoved (NodeMemberEvent ev) { Children children = (Children)this.children.get (); if (children == null) return; children.filterChildrenRemoved (ev); } /* Informs that a set of children has been reordered. * @param ev event describing the action */ public void childrenReordered (NodeReorderEvent ev) { Children children = (Children)this.children.get (); if (children == null) return; children.filterChildrenReordered (ev); } /** Does nothing. * @param ev the event */ public void nodeDestroyed (NodeEvent ev) { } } /** Filter node handle. */ private static final class FilterHandle implements Node.Handle { private Node.Handle original; static final long serialVersionUID =7928908039428333839L; public FilterHandle (Node.Handle original) { this.original = original; } public Node getNode () throws IOException { return new FilterNode (original.getNode ()); } } } /* * Log * 41 Gandalf 1.40 1/15/00 Jaroslav Tulach Equal is symetric. * 40 Gandalf 1.39 1/13/00 Jesse Glick NOI18N * 39 Gandalf 1.38 1/12/00 Jesse Glick NOI18N * 38 Gandalf 1.37 12/27/99 Jaroslav Tulach #5042 * 37 Gandalf 1.36 12/27/99 Jaroslav Tulach #5042 * 36 Gandalf 1.35 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 35 Gandalf 1.34 10/6/99 Jaroslav Tulach #1787 * 34 Gandalf 1.33 10/4/99 Jesse Glick [JavaDoc] * 33 Gandalf 1.32 9/16/99 Jesse Glick [JavaDoc] * 32 Gandalf 1.31 9/16/99 Jaroslav Tulach equals and hashcode * redefined for isDefault only. * 31 Gandalf 1.30 9/15/99 Jesse Glick Removed delegation of * equals() and hashCode(), which break many things. Also fixed another * potential bug in isDefault(). * 30 Gandalf 1.29 9/15/99 Jesse Glick Added configurable * delegation masks, solving many problems with display names, deletion, * etc. Also fixed possible bug: isDefault () would incorrectly return * true if Children.LEAF (resp. FilterChildren) were used when the original * was not (resp. was) a leaf. * 29 Gandalf 1.28 9/2/99 Jaroslav Tulach getNodes improvement. * 28 Gandalf 1.27 8/27/99 Jaroslav Tulach * 27 Gandalf 1.26 8/9/99 Ian Formanek Generated Serial Version * UID * 26 Gandalf 1.25 7/29/99 Jaroslav Tulach Handle implemented. * 25 Gandalf 1.24 7/12/99 Jesse Glick FilterNode.Children.createNodes * non-final. * 24 Gandalf 1.23 7/2/99 Jesse Glick Node.drag abstract. * 23 Gandalf 1.22 6/30/99 Ian Formanek Fixed to compile with new * Drag'n'drop datatransfer * 22 Gandalf 1.21 6/28/99 Ian Formanek Removed obsoleted import * 21 Gandalf 1.20 6/24/99 Jesse Glick Nodes can specify context * help (not yet retrieved by anything, though). * 20 Gandalf 1.19 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 19 Gandalf 1.18 6/8/99 Jaroslav Tulach Filter node updates * correctly when change order is performed. * 18 Gandalf 1.17 6/5/99 Jesse Glick [JavaDoc] * 17 Gandalf 1.16 5/27/99 Jesse Glick [JavaDoc] * 16 Gandalf 1.15 5/25/99 Jaroslav Tulach Fix #1889 * 15 Gandalf 1.14 5/15/99 Jesse Glick [JavaDoc], and * ChildrenAdapter made private since it is useless to subclass. * 14 Gandalf 1.13 4/21/99 Jaroslav Tulach DataObjects can be * finalized * 13 Gandalf 1.12 4/21/99 Jesse Glick [JavaDoc] * 12 Gandalf 1.11 4/20/99 Jaroslav Tulach * 11 Gandalf 1.10 4/20/99 Jaroslav Tulach Children supports weak * references. * 10 Gandalf 1.9 4/9/99 Ian Formanek Removed debug printlns * 9 Gandalf 1.8 3/24/99 Jan Jancura getOriginal must be * protected * 8 Gandalf 1.7 3/17/99 Jesse Glick [JavaDoc] * 7 Gandalf 1.6 3/12/99 Jan Jancura Bug in method destroy () * 6 Gandalf 1.5 2/26/99 David Simonek * 5 Gandalf 1.4 2/25/99 Jaroslav Tulach Change of clipboard * management * 4 Gandalf 1.3 2/16/99 David Simonek * 3 Gandalf 1.2 2/5/99 Jaroslav Tulach Changed new from template * action * 2 Gandalf 1.1 1/7/99 Jaroslav Tulach * 1 Gandalf 1.0 1/5/99 Ian Formanek * $ */